﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Composition;
using BTGICS.CommonLibrary;

namespace BTGICS.Guess
{
    [Export( typeof( IPlugIn ) )]
    public class PlugIn : IPlugIn
    {
        #region Private Properties
        private bool GameIsOver = false;
        private int Limit = 0;
        private int NumberOfGuesses = 0;
        private int ThinkingOfNumber = 0;
        private int ParForLimit = 0;
        private Random rnd = new Random();
        #endregion
        #region IPlugIn Members
        public string Name
        {
            get
            {
                return "Guess";
            }
        }
        public string Description
        {
            get
            {
                return "This is a guessing game. I.E. I'm thinking of a number between 1 and 10.";
            }
        }
        public void Run()
        {
            Console.Clear();
            Intro();
            while( !GameIsOver )
            {
                Initialize();
                ThinkOfNumber();
                StartGuessing();
                Console.WriteLine( "Do you want to play again? (Y or N)" );
                string ans = Console.ReadLine();
                Console.Clear();
                if( ans.ToUpper() != "Y" )
                {
                    GameIsOver = true;
                }
            }
            Console.WriteLine( "Good Bye\r\n" );
        }
        #endregion
        #region Initialize
        private void Initialize()
        {
            NumberOfGuesses = 0;
            Console.Write( "What limit do you want? " );
            while( true )
            {
                Limit = GetInput();
                if( Limit > 0 )
                {
                    break;
                }
            }
            ParForLimit = ( int ) ( Math.Log( Limit ) / Math.Log( 2 ) ) + 1;
        }
        #endregion
        #region Intro
        private void Intro()
        {
            Console.WriteLine( "This is a guessing game.  I'll think of a number between 1 and any limit you \\r\nwant.  Then you have to guess what it is.\r\n" );
        }
        #endregion
        #region Think Of Number
        private void ThinkOfNumber()
        {
            ThinkingOfNumber = rnd.Next( Limit ) + 1;
            Console.WriteLine( "I am thinking of a number between 1 and {0}.\r\nNow you try to guess what it is.", Limit );
        }
        #endregion
        #region Start Guessing
        private void StartGuessing()
        {
            while( true )
            {
                NumberOfGuesses++;
                Console.Write( "Guess #{0}: ", NumberOfGuesses );
                int guess = GetInput();
                if( guess > ThinkingOfNumber )
                {
                    Console.WriteLine( "Too high.  Try a smaller answer." );
                }
                else if( guess < ThinkingOfNumber )
                {
                    Console.WriteLine( "Too low.  Try a bigger answer." );
                }
                else
                {
                    Console.WriteLine( "That's it.  You got it in {0} {1}.", NumberOfGuesses, NumberOfGuesses == 1 ? "try" : "tries" );
                    if( NumberOfGuesses == ParForLimit )
                    {
                        Console.WriteLine( "Good" );
                    }
                    else if( NumberOfGuesses < ParForLimit )
                    {
                        Console.WriteLine( "Very Good" );
                    }
                    else
                    {
                        Console.WriteLine("You should have been able to guess it in {0}.", ParForLimit);
                    }
                    return;
                }
            }
        }
        #endregion
        #region Get Input
        private int GetInput()
        {
            while( true )
            {
                Console.ForegroundColor = ConsoleColor.Green;
                string ans = Console.ReadLine();
                Console.ResetColor();
                try
                {
                    return int.Parse( ans );
                }
                catch
                {
                    switch( rnd.Next( 4 ) )
                    {
                        case 0:
                            Console.WriteLine( "Last time I checked, {0} was not a number.", ans );
                            break;
                        case 1:
                            Console.WriteLine( "Huh?" );
                            break;
                        case 2:
                            Console.WriteLine( "Sorry, please enter a number." );
                            break;
                        case 3:
                            Console.WriteLine( "Only numbers please." );
                            break;
                    }
                }
            }

        }
        #endregion
   
    }
}
